#!/bin/bash
VERSION="1.7.1"

GNAPNAME=`basename $0`
echo "GNAP overlay tool ${GNAPNAME} ${VERSION}"
GNAPCORE="/usr/lib/gnap/gnap-core.tar"
GNAPMBR="/usr/lib/gnap/mbr/mbr.bin"

getcols() {
	echo "$2"
}

G=$'\e[32;01m'
B=$'\e[31;01m'
N=$'\e[0m'
W=$'\e[33;01m'
K=$'\e[34;01m'
C="`stty size 2> /dev/null`"
C="`getcols ${C}`"
C=$((${C} - 7))
E=$'\e['${C}'G' 

gwarn() {
	echo -e " ${W}*${N} ${*}"
}

gconfirm() {
	if [ "${FORCEYES}" == "1" ]; then
		gwarn "${*} forced to yes"
	else
		read -ep " ${W}*${N} ${*} [N]: " answer
		if [ "${answer}" != "y" -a "${answer}" != "Y" ]; then
			if [ "${TEMPDIRSTART}" == "1" ]; then
				cleanup
				fi
				echo "Overlay aborted !"
			exit 2
		fi
	fi
}

gbegin() {
	echo -ne " ${G}*${N} ${*}..."
}

gtest() {
	continued=0
	if [ "$#" -gt 0 ] && [ "$1" == "continued" ]; then
		shift
		continued=1
	fi
	
	if [ "$#" -eq 0 ] || ([ -n "$1" ] && [ "$1" -eq 0 ]); then
		if [ "${continued}" -eq 0 ]; then
			echo -e "${E}  ${K}[ ${G}ok${K} ]${N}"
		fi
	else
		echo -e "${E}  ${K}[ ${B}!!${K} ]${N}"		
		if [ "$#" -ge 2 ]; then
			shift
			echo -en " ${B}*${N} ${*}"
			echo -e "${E}  ${K}[ ${B}!!${K} ]${N}"
			if [ "${TEMPDIRSTART}" == "1" ]; then
			  cleanup
			fi
			echo "Overlay failed, try ${GNAPNAME} -h for more help"
			exit 1
		fi
	fi
}

usage() {
	echo
	echo "Usage:"
	echo "  ${GNAPNAME} -i isoname -o overlay [ options ]"
	echo "  ${GNAPNAME} -d hostdisk -r rootdev -o overlay [ options ]"
	echo
	echo "Common options:"
	echo "  -o overlay    Overlay directory or tbz2 file"
	echo "  -c conf       overlay.conf file to use (if not in overlays)"
	echo "  -g gnap_core  Use specific GNAP core tarball file"
	echo "  -n            Do not use the GNAP castle logo"
	echo "  -f            Force all answers to yes (dangerous !)"
	echo
	echo "Options for ISO target (create an ISO containing bootable CD):"
	echo "  -i isoname    Customized LiveCD ISO output file name"
	echo
	echo "Options for disk target (install to a disk plugged in system):"
	echo "  -d hostdisk   Disk to install to, as seen on current host"
	echo "  -r rootdev    Boot device name as seen from target system"
	echo "  -m            Cache filesystem in memory to reduce media wear"
	echo "  -s            Use serial console on ttyS0"
	echo
	echo "Please man ${GNAPNAME} for more details."
}

cleanup() {
	gbegin "Cleaning temporary directories"
	if [ -d "${TEMPCOREDIR}" ]; then
		rm -rf "${TEMPCOREDIR}"
		gtest continued $? "Failed to remove ${TEMPCOREDIR}"
	fi
	
	if [ -d "${TEMPOVERDIR}" ]; then
		rm -rf "${TEMPOVERDIR}"
		gtest continued $? "Failed to remove ${TEMPOVERDIR}"
	fi
	
	if [ -d "${TEMPMOUNTDIR}" ]; then
		rm -rf "${TEMPMOUNTDIR}"
		gtest continued $? "Failed to remove ${TEMPMOUNTDIR}"
	fi
	gtest 0
}

if [ "$#" -eq "0" ]||[ "$1" == "-h" ]; then
	usage
	exit 0
fi

gbegin "Checking parameters"

# Read options
while getopts ":hg:o:c:nfi:d:r:ms" options; do
	case ${options} in
		h ) usage
			exit 0;;
		g ) GNAPCORE="${OPTARG}";;
		o ) OVERLAYS="${OVERLAYS} ${OPTARG}";;
		c ) OVERLAYCONF="${OPTARG}";;
		n ) NOLOGO="1";;
		f ) FORCEYES="1";;
		i ) OUTPUT="${OPTARG}"
			TYPE="iso";;
		d ) OUTPUT="${OPTARG}"
			TYPE="disk";;
		r ) TARGETROOT="${OPTARG}";;
		m ) CACHE="docache ";;
		s ) SERIAL="console=ttyS0,19200n81";;
		* ) gtest 1 "Specified options are incomplete or unknown !";;
	esac
done

# Target type (-i or -d) is needed
test "${TYPE}" != ""
gtest continued $? "Please specify a target (-i or -d option)"

# Core file is required
test -f "${GNAPCORE}" 
gtest continued $? "Please specify a valid GNAP core file (-g option)"

# if disk type, doublecheck everything is ok
if [ "${TYPE}" == "disk" ]; then
	PARENTDEV="${OUTPUT:0:$((${#OUTPUT}-1))}"
	test -b "${PARENTDEV}"
	gtest continued $? "${PARENTDEV} device does not exist on this system"
	test -b "${OUTPUT}"
	gtest continued $? "${OUTPUT} partition does not exist on this system"
fi  

# At least one overlay is required
test "${OVERLAYS}${OVERLAYCONF}" != ""
gtest $? "Please specify at least an overlay (-o) or config file (-c)"

# Warning for disk type targets 
if [ "${TYPE}" == "disk" ]; then
	gwarn "Warning : you have selected disk install"
	gwarn "Make sure you are root or have full access to ${OUTPUT}"
	gwarn "${PARENTDEV} must have an MBR installed, run:"
	gwarn "${W}dd if=${GNAPMBR} of=${PARENTDEV} bs=512 count=1${N} if needed"
	gwarn "${OUTPUT} must contain an active partition:"
	gwarn " use ${W}fdisk ${PARENTDEV}${N} if needed"
	gwarn "Current data on ${OUTPUT} will be ${B}destroyed${N} !" 
	gconfirm "Are your sure you want to continue"
fi

# Common actions
gbegin "Expanding ${GNAPCORE} core"
TEMPDIRSTART=1
TEMPCOREDIR=`mktemp -d -t gnapcore_XXXXXXXXXX`
gtest continued $? "Failed to make tmpfile"
tar x -C "${TEMPCOREDIR}" -f "${GNAPCORE}"
gtest $? "Failed to extract core"

gbegin "Preparing overlay"
TEMPOVERDIR=`mktemp -d -t gnapover_XXXXXX`
gtest $? "Failed to make tmpdir"
for overlay in ${OVERLAYS} ; do
	if [ -d ${overlay} ]; then
		gbegin "Adding ${overlay} (directory overlay)"
		cp -rp ${overlay}/* "${TEMPOVERDIR}"
		gtest $? "Failed to copy ${overlay}" 
	else
		gbegin "Adding ${overlay} (conflet file)"
		tar jxf "${overlay}" -C "${TEMPOVERDIR}" 2>/dev/null
		gtest $? "${overlay} is not a valid conflet file (tbz2 format)"
	fi
done
if [ "${OVERLAYCONF}" != "" ]; then
	gbegin "Adding ${OVERLAYCONF} (overlay.conf file)"
	if [ ! -d "${TEMPOVERDIR}/etc" ]; then
		mkdir "${TEMPOVERDIR}/etc"
		gtest continued $? "Failed to create /etc overlay directory"
	fi
	cp "${OVERLAYCONF}" "${TEMPOVERDIR}/etc/overlay.conf"
	gtest $? "Failed to copy ${OVERLAYCONF}"
fi
gbegin "Creating overlay tarball"
test -f "${TEMPOVERDIR}/etc/overlay.conf"
gtest continued $? "Specified overlays do not contain any etc/overlay.conf"
tar zc -C "${TEMPOVERDIR}" --exclude CVS -f "${TEMPCOREDIR}/overlay.tgz" .
gtest $? "Failed to create overlay tarball"

DATE=`date --utc`
if [ "${NOLOGO}" == "1" ]; then
	echo "GNAP ${VERSION}" > "${TEMPCOREDIR}/isolinux/boot.msg"
fi
if [ "${OVERLAYS}" != "" ]; then
	echo "Overlaid with ${OVERLAYS} on ${DATE}" \
		>> "${TEMPCOREDIR}/isolinux/boot.msg"
fi

# Target specific actions
if [ "${TYPE}" == "iso" ]; then
	if [ -f "${OUTPUT}" ]; then
		gconfirm "File ${OUTPUT} already exists, overwrite ?"
	fi
	rm "${TEMPCOREDIR}/syslinux.cfg"
	gbegin "Building ${OUTPUT} ISO file"
	mkisofs -quiet -J -r -l -x "${TEMPCOREDIR}/.." -o "${OUTPUT}" \
		-b isolinux/isolinux.bin -c isolinux/boot.cat \
		-no-emul-boot -boot-load-size 4 -boot-info-table "${TEMPCOREDIR}"
	gtest $?

else

	TEMPMOUNTDIR=`mktemp -d -t gnapmount_XXXXXX`
	gtest continued $? "Failed to make tmpdir"
	
	gbegin "Formatting ${OUTPUT}"
	mkfs.msdos "${OUTPUT}" > /dev/null 2>&1
	gtest $?
	
	gbegin "Mounting ${OUTPUT}"
	mount -t msdos -o sync "${OUTPUT}" "${TEMPMOUNTDIR}"
	gtest $?
	
	gbegin "Copying files"
	cp ${TEMPCOREDIR}/syslinux.cfg			${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/isolinux/gentoo.igz	${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/isolinux/gentoo		${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/isolinux/*.msg		${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/livecd		${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/overlay.tgz			${TEMPMOUNTDIR}/			&&\
	cp ${TEMPCOREDIR}/livecd.squashfs		${TEMPMOUNTDIR}/livecd.sfs	&&\
	sed -i \
		"s:cdroot:cdroot=/dev/${TARGETROOT} ${CACHE}${SERIAL}:" \
		"${TEMPMOUNTDIR}/syslinux.cfg"
	gtest $?
		
	gbegin "Unmounting ${OUTPUT}"
	umount "${TEMPMOUNTDIR}"
	gtest $?
		
	gbegin "Syslinuxing"
	export MTOOLS_SKIP_CHECK=1
	syslinux "${OUTPUT}"
	gtest $?

fi

# Successful finish
cleanup
echo "Overlay successful !"
exit 0

